﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SimpleCalcDataStructures;
using System.Collections.Generic;

namespace SimpleCalcParser
{
    public class PostFixEvaluator
    {
        public static Operand Evaluate(LinkedList<Token> input)
        {
            
            Number resultVal = new Number();    
            resultVal.NumberValue = 0;

            //begin postfix evaluation
            Stack<double> numbers = new Stack<double>();
            foreach (Token t in input)
            {
                switch (t.type)
                {
                    case TokenType.Number:
                        //check for pi and e
                        if (t.value.Equals("π"))
                        {
                            numbers.Push(Math.PI);
                        }
                        else if (t.value.Equals("e"))
                        {
                            numbers.Push(Math.E);
                        }
                        else
                        {
                            numbers.Push(Double.Parse(t.value));
                        }
                        break;
                    case TokenType.LeftAssocitiveBinaryOperator:
                    case TokenType.RightAssocitiveBinaryOperator:
                        double second = numbers.Pop();
                        double first = numbers.Pop();
                        numbers.Push(binaryOperation(t.value, first, second));
                        break;
                    case TokenType.PrimaryStart:
                        double value = numbers.Pop();
                        numbers.Push(singleValueOperation(t.value, value));
                        break;
                    default : 
                        break;
                }
            }
            //Update final answer
            resultVal.NumberValue = numbers.Pop();
            
            return resultVal;
        }

        private static double singleValueOperation(string opType, double value)
        {
            if (opType.Equals("sin"))
            {
                return Math.Sin(value);
            }
            else if (opType.Equals("cos"))
            {
                return Math.Cos(value);
            }
            else if (opType.Equals("tan"))
            {
                return Math.Tan(value);
            }
            else //square root
            {
                return Math.Sqrt(value);
            }

        }

        private static double binaryOperation(string p, double first, double second)
        {
            if (p.Equals("+"))
            {
                return first + second;
            }
            else if (p.Equals("−"))
            {
                return first - second;
            }
            else if (p.Equals("*"))
            {
                return first * second;
            }
            else if (p.Equals("/"))
                return first / second;
            else //raised to power
                return Math.Pow(first, second);

        }
    }
}
